问题描述
最近在使用redis的发布订阅系统来做公司项目的消息队列。一台服务器发布消息,多台服务器订阅获取消息。在系统使用高峰期上午10点左右偶发性的有些服务器的Redis链接被断开并报错:
Uncaught RedisException: socket error on read socket
查看redis日志后发现这么一条错误日志:
Client id=319669 addr=192.168.1.10:52846 fd=83 name= age=534515 idle=1 flags=N db=0 sub=2 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=882 omem=452122 events=rw cmd=subscribe scheduled to be closed ASAP for overcoming of output buffer limits
解决方式
错误日志很明显的说明对于即将关闭的这个链接有输出缓冲区的限制。初步判断是由于发送消息的服务器产生的消息过多。订阅的服务器来不及消费,并达到了系统输出缓冲区大小的限制。从而关闭了这个链接。谷歌了一下发现redis.conf有如下的限制。
# The client output buffer limits can be used to force disconnection of clients
# that are not reading data from the server fast enough for some reason (a
# common reason is that a Pub/Sub client can't consume messages as fast as the
# publisher can produce them).
#
# The limit can be set differently for the three different classes of clients:
#
# normal -> normal clients including MONITOR clients
# slave -> slave clients
# pubsub -> clients subscribed to at least one pubsub channel or pattern
#
# The syntax of every client-output-buffer-limit directive is the following:
#
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
#
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
# So for instance if the hard limit is 32 megabytes and the soft limit is
# 16 megabytes / 10 seconds, the client will get disconnected immediately
# if the size of the output buffers reach 32 megabytes, but will also get
# disconnected if the client reaches 16 megabytes and continuously overcomes
# the limit for 10 seconds.
#
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read.
#
# Instead there is a default limit for pubsub and slave clients, since
# subscribers and slaves receive data in a push fashion.
#
# Both the hard or the soft limit can be disabled by setting them to zero.
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
翻译一下redis关于输出缓冲区限制的注释
# The client output buffer limits can be used to force disconnection of clients
客户端输出缓冲区限制可用于强制断开客户端
# that are not reading data from the server fast enough for some reason (a
# common reason is that a Pub/Sub client can't consume messages as fast as the
# publisher can produce them).
由于某些原因,不能很快地从服务器读取数据(一个常见的原因是,Pub/Sub 客户端不能像发布者那样快速地消耗消息。)
# The limit can be set differently for the three different classes of clients:
对于三种不同类型的客户端,可以设置不同的限制:
# normal -> normal clients including MONITOR clients
普通连接
# slave -> slave clients
与slave之间的连接
# pubsub -> clients subscribed to at least one pubsub channel or pattern
客户端订阅通过普通订阅或者模式匹配订阅了至少一个频道的链接
# The syntax of every client-output-buffer-limit directive is the following:
每个客户端输出缓冲区限制指令的语法如下:
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
class:表示链接类型
hard:表示允许该链接类型客户端的输出缓存区大小
soft:跟seconds配合使用,允许在seconds秒内缓存区限制的内存大小。
seconds:配合soft使用。同上
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
一旦达输出缓冲区的内存大小达到了head limit(硬限制) 或者如果输出缓冲区的内存大小达到了soft limit(软限制)且持续时间达到了
seconds 客户端立即断链接
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read
上面吧啦吧啦的一大堆是在说正常的客户端不受限制,因为它们没有在不请求的情况下接受数据
(如get命令:发送一个请求到服务器端,然后接收服务器的数据)。
既然正常的客户端不受限制那么来看它的默认配置:client-output-buffer-limit normal 0 0 0。
可以看出通通设置为0是不受缓冲区大小的限制。
# Both the hard or the soft limit can be disabled by setting them to zero.
通过设置为零,硬或软限制都可以被禁用。
总结
通过调整pubsub的缓存区的限制可以解决因为客户端缓存区大小限制导致的redis链接断开的问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。